package org.javaforever.infinity.limitedverb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.javaforever.infinity.core.Writeable;
import org.javaforever.infinity.domain.Domain;
import org.javaforever.infinity.domain.Field;
import org.javaforever.infinity.domain.Method;
import org.javaforever.infinity.domain.Signature;
import org.javaforever.infinity.domain.Statement;
import org.javaforever.infinity.domain.Type;
import org.javaforever.infinity.generator.NamedStatementGenerator;
import org.javaforever.infinity.generator.NamedStatementListGenerator;
import org.javaforever.infinity.utils.DomainTokenUtil;
import org.javaforever.infinity.utils.InterVarUtil;
import org.javaforever.infinity.utils.StringUtil;
import org.javaforever.infinity.utils.TableStringUtil;
import org.javaforever.infinity.utils.WriteableUtil;

public class CountSearchByFieldsRecords extends NoControllerVerb {

	@Override
	public Method generateDaoImplMethod() throws Exception{	
		Method method = new Method();
		method.setStandardName("countSearch"+this.domain.getCapFirstPlural()+"ByFieldsRecords");	
		method.setReturnType(new Type("Long"));
		method.addAdditionalImport(this.domain.getPackageToken()+".domain."+this.domain.getStandardName());
		method.addSignature(new Signature(1,"connection",new Type("Connection","java.sql"),"java.sql"));
		method.addSignature(new Signature(2,this.domain.getLowerFirstDomainName(),this.domain.getType(),this.domain.getPackageToken(),"Param(value=\""+this.domain.getLowerFirstDomainName()+"\")"));
		
		List<Writeable> list = new ArrayList<Writeable>();
		
		list.add(new Statement(100,2,"try {"));
		list.add(new Statement(400L,2,"String query = \" select count(*) countSum from "+ domain.getDbPrefix() + TableStringUtil.domainNametoTableName(domain)+" where 1=1 \";"));
		
		long serial = 500L;
		Set<Field> fields = this.domain.getFieldsWithoutId();
		for (Field f:fields){
			if (f.getFieldType().equalsIgnoreCase("string")){
				list.add(new Statement(serial,2,"if ("+this.domain.getLowerFirstDomainName()+"."+f.getGetterCall()+"!=null && !\"\".equals("+this.domain.getLowerFirstDomainName()+"."+f.getGetterCall()+")){"));
				list.add(new Statement(serial+100,3,"query += \" and "+DomainTokenUtil.changeDomainFieldtoTableColum(f.getFieldName())+" like ? \";"));
			}else{
				list.add(new Statement(serial,2,"if ("+this.domain.getLowerFirstDomainName()+"."+f.getGetterCall()+"!=null ){"));
				list.add(new Statement(serial+100,3,"query += \" and "+DomainTokenUtil.changeDomainFieldtoTableColum(f.getFieldName())+" = ? \";"));
			}
			list.add(new Statement(serial+200,2,"}"));
			serial += 300L;
		}
		list.add(new Statement(serial,2,"query += \";\";"));
		list.add(new Statement(serial+100,2,"//System.out.println(\"JerryDebug:query:\"+query);"));
		list.add(new Statement(serial+200,2,""));
		list.add(new Statement(serial+300,2,"int serial = 1;"));
		list.add(new Statement(serial+400,2,"PreparedStatement ps = connection.prepareStatement(query);"));
		list.add(new Statement(serial+500,2,""));
		
		serial += 600L;

		for (Field f:fields){
			if (f.getFieldType().equalsIgnoreCase("string")){
				list.add(new Statement(serial,2,"if ("+this.domain.getLowerFirstDomainName()+"."+f.getGetterCall()+"!=null && !\"\".equals("+this.domain.getLowerFirstDomainName()+"."+f.getGetterCall()+")){"));
				list.add(new Statement(serial+100,3,"ps.setString(serial++,\"%\"+"+this.domain.getLowerFirstDomainName()+"."+f.getGetterCall()+"+\"%\");"));
			}else{
				list.add(new Statement(serial,2,"if ("+this.domain.getLowerFirstDomainName()+"."+f.getGetterCall()+"!=null ){"));
				list.add(new Statement(serial+100,3,"ps.set"+StringUtil.capFirst(f.getPrimaryType().getTypeName())+"(serial++,"+this.domain.getLowerFirstDomainName()+"."+f.getGetterCall()+");"));
			}
			list.add(new Statement(serial+200,2,"}"));
			serial += 300L;
		}
		list.add(new Statement(serial+200,2,""));
		list.add(new Statement(serial+300,2,"ResultSet result = ps.executeQuery();"));
		list.add(new Statement(serial+400,2,"Long countSum = 0L;"));
		list.add(new Statement(serial+500,2,"while(result.next()) {"));
		list.add(new Statement(serial+600,3,"countSum = result.getLong(\"countSum\");"));
		list.add(new Statement(serial+700,2,"}"));
		list.add(new Statement(serial+800,2,"return countSum;"));
		list.add(new Statement(serial+900,2,"} catch (Exception e){"));
		list.add(new Statement(serial+1000,3,"e.printStackTrace();"));
		list.add(new Statement(serial+1100,3,"return 0L;"));
		list.add(new Statement(serial+1200,2,"}"));
				
		method.setMethodStatementList(WriteableUtil.merge(list));
		return method;
	}

	@Override
	public String generateDaoImplMethodString()  throws Exception{
		Method m = this.generateDaoImplMethod();
		String s = m.generateMethodString();
		return s;
	}

	@Override
	public String generateDaoImplMethodStringWithSerial()  throws Exception{
		Method m = this.generateDaoImplMethod();
		m.setContent(m.generateMethodContentStringWithSerial());
		m.setMethodStatementList(null);
		return m.generateMethodString();
	}

	@Override
	public Method generateDaoMethodDefinition()  throws Exception{
		Method method = new Method();
		method.setStandardName("countSearch"+this.domain.getCapFirstPlural()+"ByFieldsRecords");
		method.setReturnType(new Type("Long"));
		method.addAdditionalImport(this.domain.getPackageToken()+".domain."+this.domain.getStandardName());
		method.addSignature(new Signature(1,"connection",new Type("Connection","java.sql"),"java.sql"));
		method.addSignature(new Signature(2,this.domain.getLowerFirstDomainName(),this.domain.getType(),this.domain.getPackageToken()));		
		method.setThrowException(true);
		return method;
	}

	@Override
	public String generateDaoMethodDefinitionString()  throws Exception{
		return generateDaoMethodDefinition().generateMethodDefinition();
	}

	@Override
	public Method generateServiceMethodDefinition()  throws Exception{
		Method method = new Method();
		method.setStandardName("countSearch"+this.domain.getCapFirstPlural()+"ByFieldsRecords");
		method.setReturnType(new Type("Long"));
		method.addAdditionalImport(this.domain.getPackageToken()+".domain."+this.domain.getStandardName());
		method.addSignature(new Signature(1,this.domain.getLowerFirstDomainName(),this.domain.getType()));
		method.setThrowException(true);
		
		return method;
	}

	@Override
	public String generateServiceMethodDefinitionString()  throws Exception{
		return generateServiceMethodDefinition().generateMethodDefinition();
	}

	@Override
	public Method generateServiceImplMethod()  throws Exception{
		Method method = new Method();
		method.setStandardName("countSearch"+this.domain.getCapFirstPlural()+"ByFieldsRecords");
		method.setReturnType(new Type("Long"));
		method.addAdditionalImport(this.domain.getPackageToken()+".domain."+this.domain.getStandardName());
		method.addAdditionalImport(this.domain.getPackageToken()+".dao."+this.domain.getStandardName()+"Dao");
		method.addAdditionalImport(this.domain.getPackageToken()+".service."+this.domain.getStandardName()+"Service");
		method.addSignature(new Signature(1,this.domain.getLowerFirstDomainName(),this.domain.getType()));
		method.setThrowException(true);
		method.addMetaData("Override");
		
		Method daomethod = this.generateDaoMethodDefinition();		
		List<Writeable> list = new ArrayList<Writeable>();
		list.add(NamedStatementListGenerator.generateServiceImplReturnInt(1000L, 2, InterVarUtil.DB.connection, InterVarUtil.DB.dbconf, this.domain, InterVarUtil.DB.dao, daomethod));
		method.setMethodStatementList(WriteableUtil.merge(list));

		return method;
	}

	@Override
	public String generateServiceImplMethodString()  throws Exception{
		return generateServiceImplMethod().generateMethodString();
	}

	@Override
	public String generateServiceImplMethodStringWithSerial() throws Exception{
		Method m = this.generateServiceImplMethod();
		m.setContent(m.generateMethodContentStringWithSerial());
		m.setMethodStatementList(null);
		return m.generateMethodString();
	}
	
	public CountSearchByFieldsRecords(Domain domain){
		super();
		this.domain = domain;
		this.verbName = "countSearch"+this.domain.getCapFirstPlural()+"ByFieldsRecords";
	}
	
	public CountSearchByFieldsRecords(){
		super();
	}

}
